/*
 * This code is licensed under the Apache License 2.0.
 * Read more at http://blippit.googlecode.com/
 */
package com.googlecode.blippit;

import java.io.IOException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;

/**
 * Simplified synchronous HTTP client.
 * Implementation borrows heavily from the Apache example
 * org.apache.http.examples.client.ClientExecuteDirect
 */
public class BlockingHttpClient {
	private static HttpParams defaultParameters = null;
	private static SchemeRegistry supportedSchemes = null;
	private static ClientConnectionManager ccm = null;
	private static final HttpVersion version = HttpVersion.HTTP_1_1;
	
	static class Response {
		public Response(HttpResponse r) throws IOException {
			HttpEntity entity = r.getEntity();
			code = r.getStatusLine().getStatusCode();
			status = r.getStatusLine().getReasonPhrase();
			headers = r.getAllHeaders();
			String b = null;
			if (entity != null) {
				try {
					b = EntityUtils.toString(r.getEntity());
				} catch (ParseException e) {
				} finally {
					// Clean up in case toString threw an exception
					entity.consumeContent();
				}
			}
			body = b;
		}
		public final int code;
		public final String status;
		public final Header[] headers;
		public final String body;
	}

	public static Response get(String host, int port, String path, Header[] headers)
	throws ClientProtocolException, IOException {
		final HttpHost target = new HttpHost(host, port, "http");

		DefaultHttpClient client = createHttpClient();
		HttpRequest req = new BasicHttpRequest("GET", path, version);
		if (headers != null) {
			for (Header h : headers)
				req.addHeader(h);
		}
		return new Response(client.execute(target, req));
	}

	/**
	 * Create a new HTTP client. Also creates the underlying connection manager
	 * if necessary.
	 */
	private final static DefaultHttpClient createHttpClient() {
		if (null == ccm) {
			ccm = new ThreadSafeClientConnManager(getParams(), getSchemes());
		}
		return new DefaultHttpClient(ccm, getParams());
	}

	/**
	 * Get a scheme registry, creating it if necessary.
	 */
	private final static SchemeRegistry getSchemes() {
		if (null == supportedSchemes) {
			supportedSchemes = new SchemeRegistry();
			SocketFactory sf = PlainSocketFactory.getSocketFactory();
			supportedSchemes.register(new Scheme("http", sf, 80));
		}
		return supportedSchemes;
	} // setup


	private final static HttpParams getParams() {
		if (null == defaultParameters) {
			HttpParams params = new BasicHttpParams();
			HttpProtocolParams.setVersion(params, version);
			HttpProtocolParams.setContentCharset(params, "UTF-8");
			HttpProtocolParams.setUseExpectContinue(params, true);
			defaultParameters = params;
		}
		return defaultParameters;
	}

}
